home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / XDME / Src / Var / VarsBases.c < prev    next >
C/C++ Source or Header  |  1996-09-26  |  12KB  |  588 lines

  1. #define PATCH_AVL
  2. /******************************************************************************
  3.  
  4.     MODUL
  5.     varsbases.c
  6.  
  7.     DESCRIPTION
  8.     lowlevel Variable support for DME/XDME
  9.     (Basic List/AVL-Tree Functions)
  10.  
  11.  
  12.     NOTES
  13.     Either use AVLTREES or MLISTS
  14.  
  15.     For ALL commands (even to the searches) You must use
  16.     the address of a tree/list, not the tree/list itself
  17.     (that was done to simplify source-modification: just
  18.      replace 'List'/[M]LIST by 'Tree'/APTR, and go)
  19.  
  20.     BUGS
  21.     <none known>
  22.  
  23.     TODO
  24.     More homogene Interface - Use of an opaque type
  25.     (So that silly redefinition in other modules can go away)
  26.  
  27.     EXAMPLES
  28.     -/-
  29.  
  30.     SEE ALSO
  31.     vars.c
  32.  
  33.     INDEX
  34.  
  35.     HISTORY
  36.     <see RCS-File>
  37.  
  38.  
  39. ******************************************************************************/
  40.  
  41. /*
  42. **  (C)Copyright 1992 by Bernd Noll for null/zero-soft
  43. **  All Rights Reserved
  44. **
  45. **  RCS Header: $Id: varsbases.c,v 1.65 92/12/04 21:00:32 b_noll Exp $
  46. **
  47. **  Basic Functions to work with trees/lists of DME-Variables
  48. **  Put together to start a little bit of modularisation
  49. **  in the sources.
  50. **
  51. */
  52.  
  53. /**************************************
  54.         Includes
  55. **************************************/
  56. #define TNODE struct TreeNode
  57. #define VARS  struct _VARS
  58. #define VBASE TNODE *
  59.  
  60. #include "defs.h"
  61. #include "AVL.h"
  62.  
  63. /**************************************
  64.        Exports
  65. **************************************/
  66. /* --- You can only use either LISTS or AVL-Trees!!! */
  67.  
  68. /* Vars Operations on trees */
  69. Prototype void     DelAllVarsFromTree ( VBASE * tree );
  70. Prototype void     DelVarFromTree     ( VBASE * tree, char * name );
  71. Prototype char * GetVarFromTree     ( VBASE * tree, char * name );
  72. Prototype void     SetVarIntoTree     ( VBASE * tree, char * name, char * value );
  73.  
  74.  
  75. /* Lists Operations in Common */
  76. Prototype char* names2string   ( MLIST* list, char* buffer, char delimiter, void* filter );  /* assumes buffer is 1/4k * BUFFERS chgars long */
  77. Prototype int    numnodes       ( MLIST* list );
  78. Prototype NODE* findnode       ( MLIST* list, char* name, short len );
  79.  
  80. /* Vars Operations on lists */
  81. Prototype void    DelAllVarsFromList ( MLIST* list );
  82. Prototype void    DelVarFromList ( MLIST* list, char* name );
  83. Prototype char* GetVarFromList ( MLIST* list, char* name );
  84. Prototype void    SetVarIntoList ( MLIST* list, char* name, char* value );
  85.  
  86.  
  87.  
  88.  
  89. /**************************************
  90.       Interne Defines & Strukturen
  91. **************************************/
  92. #ifdef PATCH_AVL
  93. # ifdef TEST
  94. #  define error printf
  95. #  define nomemory()
  96. # endif
  97.  
  98. struct _VARS
  99. {
  100.     TNODE  Node;
  101.     char * Str;
  102. };
  103.  
  104. #else
  105.  
  106. typedef struct _VARS
  107. {
  108.     NODE  Node;
  109.     char * Str;
  110. };
  111.  
  112. #define VBASE MLIST
  113.  
  114. #endif /* (not) PATCH_AVL */
  115.  
  116.  
  117.  
  118. /**************************************
  119.       Implementation
  120. **************************************/
  121. #ifdef PATCH_AVL
  122.  
  123.  
  124. /*
  125. **  DelAllVarsFromTree()
  126. **    recursively remove all nodes from a certain tree
  127. **    and free them and their associated names&values
  128. */
  129.  
  130. void
  131. DelAllVarsFromTree (VBASE * tree)
  132. {
  133.     if (!tree || !(*tree)) {
  134.     return;
  135.     } /* if */
  136.  
  137.     DelAllVarsFromTree(&(*tree)->tn_Left);        /* first free its sons */
  138.     DelAllVarsFromTree(&(*tree)->tn_Right);
  139.  
  140.     free((*tree)->tn_Name);                       /* then free it and all its subs */
  141.     free(((VARS*)*tree)->Str);
  142.     free((*tree));
  143.  
  144. } /* DelAllVarsFromTree */
  145.  
  146.  
  147. /*
  148. **  SetVarIntoTree()
  149. **    define a node with a cetain name and value in
  150. **    a given tree if therew is already a node of the
  151. **    chosen name the previous node is removed
  152. **    (actually only the old value is removed)
  153. **    if any allocation went wrong, call nomemory()
  154. */
  155.  
  156. void
  157. SetVarIntoTree (VBASE* tree, char* name, char* value)
  158. {
  159.     VARS* v  = NULL;
  160.     char* vn = NULL;
  161.     char* vv = NULL;
  162.  
  163.     if ((v = (VARS*)AVL_Find(tree, name)))
  164.     {
  165.     if ((vv = strdup(value)))
  166.     {
  167.         free(v->Str);
  168.         v->Str = vv;
  169.         return;
  170.     } /* if malloced */
  171.     v = NULL; /* avoid freeing the found node */
  172.     } else
  173.     {
  174.     v = malloc(sizeof(VARS));
  175.     vv = strdup(value);
  176.     vn = strdup(name);
  177.     if (v && vv && vn)
  178.     {
  179.         v->Str = vv;
  180.         v->Node.tn_Name = vn;
  181.         AVL_Append (tree, (TNODE *)v);
  182.         return;
  183.     } /* if malloced */
  184.     } /* if (no) old node */
  185.  
  186.     /* --- if we didn't return prior, (if everything worked fine) remove all allocated data */
  187.     if (v)  free(v);
  188.     if (vv) free(vv);
  189.     if (vn) free(vn);
  190.     nomemory();
  191.     abort2();
  192. } /* SetVarIntoTree */
  193.  
  194.  
  195.  
  196.  
  197. /*
  198. **  DelVarFromTree()
  199. **    remove a certain node (found w/ FindTreeNode)
  200. **    from a given tree; do not panik, if there is no
  201. **    node found
  202. */
  203.  
  204. void
  205. DelVarFromTree (VBASE* tree, char* name)
  206. {
  207.     VARS *v = NULL;
  208.  
  209.     if ((v = (VARS*)AVL_Find(tree, name)))
  210.     {  /* if there is a node of the right name */
  211.     AVL_Remove (tree, (TNODE *)v);         /* remove it and all its subs */
  212.     free(v->Node.tn_Name);
  213.     free(v->Str);
  214.     free(v);
  215.     } /* if */
  216. } /* DelVarFromTree */
  217.  
  218.  
  219.  
  220.  
  221.  
  222. /*
  223. **  GetVarFromTree()
  224. **    find a node in a certain tree (w/ FindTreeNode)
  225. **    duplicate its value and return the copy
  226. **    return NULL if there was no node found
  227. **    and call nomemory() if duplicate failed
  228. */
  229.  
  230. char*
  231. GetVarFromTree (VBASE* tree, char* name)
  232. {
  233.     char* str = NULL;
  234.     VARS* v   = NULL;
  235.  
  236.     if ((v = (VARS*)AVL_Find(tree, name)))
  237.     { /* if there is a node of the right name */
  238.     if ((str = strdup(v->Str)))
  239.     {        /* return a copy of its value */
  240.         return(str);
  241.     } else
  242.     {
  243.         nomemory();
  244.         abort(NULL);
  245.     } /* if */
  246.     } /* if */
  247.     return(NULL);
  248. } /* GetVarFromTree */
  249.  
  250.  
  251.  
  252. #ifdef TEST
  253.  
  254.  
  255. void zeigebaum(TNODE* t)
  256. {
  257.     if (t==NULL)
  258.     {
  259.     printf( "-" );
  260.     return;
  261.     }
  262.  
  263.     printf("(%d%s ",t->tn_Balance,t->tn_Name);
  264.     printf("L");
  265.     zeigebaum(t->tn_Left);
  266.     printf("R");
  267.     zeigebaum(t->tn_Right);
  268.     printf(")");
  269. } /* zeigebaum */
  270.  
  271.  
  272.  
  273.  
  274. char* testnamen[] =
  275. {
  276.     "prag",
  277.     "lima",
  278.     "tokio",
  279.     "bonn",
  280.     "paris",
  281.     "sofia",
  282.     "wien",
  283.     "bern",
  284.     "kairo",
  285.     "oslo",
  286.     "rom",
  287.     "athen",
  288.     NULL };
  289.  
  290.  
  291.  
  292. int main(int ac, char* av[])
  293. {
  294.     char** tt;
  295.     char buffer [100];
  296.  
  297.     TNODE* staedte = NULL;
  298.     TNODE* rem = NULL;
  299.  
  300.     for (tt = testnamen; *tt; tt++)
  301.     {
  302.     printf(">%s\n",*tt);
  303.     SetVarIntoTree(&staedte, *tt, "");
  304. /* gets      (buffer); */
  305.     } /* for */
  306.  
  307.     zeigebaum (staedte);
  308.     rem = AVL_Find (&staedte, "bonn");
  309.     printf ("\nrem == %08lx %s\n", rem, rem->tn_Name);
  310.  
  311.     AVL_Remove (&staedte, rem);
  312.  
  313.  
  314.     zeigebaum(staedte);
  315.     puts ("");
  316. } /* main */
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323. #endif /* TEST */
  324.  
  325.  
  326. #else /* ! PATCH_AVL */
  327.  
  328.  
  329. /*
  330. **  GetVarFromList()
  331. **    find a node in a certain list (w/ FindName)
  332. **    duplicate its value and return the copy
  333. **    return NULL if there was no node found
  334. **    and call nomemory() if duplicate failed
  335. */
  336.  
  337. char*
  338. GetVarFromList (VBASE* list, char* name)
  339. {
  340.     char* str = NULL;
  341.     VARS* v   = NULL;
  342.  
  343.     if ((v = (VARS*)FindName((LIST*)list, name)))
  344.     { /* if there is a node of the right name */
  345.     if ((str = strdup(v->Str)))
  346.     {        /* return a copy of its value */
  347.         return(str);
  348.     } else
  349.     {
  350.         nomemory();
  351.         abort(NULL);
  352.     } /* if */
  353.     } /* if */
  354.     return(NULL);
  355. } /* GetVarFromList */
  356.  
  357.  
  358.  
  359. /*
  360. **  DelVarFromList()
  361. **    remove a certain node (found w/ FindName)
  362. **    from a given list; do not panik, if there is no
  363. **    node found
  364. */
  365.  
  366. void
  367. DelVarFromList (VBASE* list, char* name)
  368. {
  369.     VARS *v = NULL;
  370.  
  371.     if ((v = (VARS*)FindName((LIST*)list, name)))
  372.     { /* if there is a node of the right name */
  373.     Remove((NODE *)v);                        /* remove it and all its subs */
  374.     free(v->Node.ln_Name);
  375.     free(v->Str);
  376.     free(v);
  377.     } /* if */
  378. } /* DelVarFromList */
  379.  
  380.  
  381.  
  382. /*
  383. **  DelAllVarsFromList()
  384. **    remove all nodes from a certain list
  385. **    and free them and their associated names&values
  386. */
  387.  
  388. void
  389. DelAllVarsFromList (VBASE* list)
  390. {
  391.     VARS* v = NULL;
  392.  
  393.     while ((v = (VARS*)RemHead((LIST*)list)))
  394.     {    /* while there is an entry left in the list */
  395.     free(v->Node.ln_Name);                  /* free it and all its subs */
  396.     free(v->Str);
  397.     free(v);
  398.     } /* while */
  399. } /* DelAllVarsFromList */
  400.  
  401.  
  402.  
  403. /*
  404. **  SetVarIntoList()
  405. **    define a node with a cetain name and value in
  406. **    a given list if therew is already a node of the
  407. **    chosen name the previous node is removed
  408. **    (actually only the old value is removed)
  409. **    if any allocation went wrong, call nomemory()
  410. */
  411.  
  412. void
  413. SetVarIntoList (VBASE* list, char* name, char* value)
  414. {
  415.     VARS* v  = NULL;
  416.     char* vn = NULL;
  417.     char* vv = NULL;
  418.  
  419. #ifdef N_DEF
  420.     /* --- First it is checked, if You have a Special variable */
  421.     /*
  422.     ** these checks may be object of some changes in near future
  423.     ** - I do now think, that it would be quite better
  424.     ** to introduce a new function SETSPC for special variables
  425.     ** and to call "SETLOCAL <num>" to set a local flag instead of "SET i<num>"
  426.     */
  427.     if (SetAnyFlag(name, value) || SetSpecialInt(name, value)
  428.     || SetSpecialVar(name, value) )
  429.     {
  430.     return();
  431.     } /* if */
  432. #endif /* N_DEF */
  433.  
  434.     /*
  435.     **    that routine is a little bit longer than the old one,
  436.     **    but we need not free all data of older entries any
  437.     **    more, so memory fragmentation should be reduced a bit:
  438.     **    if there's an older entry, simply replace its value
  439.     **    by the new one, else create a full new entry.
  440.     */
  441.     if ((v = (VARS*)FindName((LIST*)list, name)))
  442.     {
  443.     if (vv = strdup(value))
  444.     {
  445.         free(v->Str);
  446.         v->Str = vv;
  447.         /* --- it might be senseful moving the changed entry to startoflist */
  448.         /* Remove(v); */
  449.         /* AddHead((LIST*)list, v) */
  450.         return;
  451.     } /* if malloced */
  452.     v = NULL; /* avoid removing the found node */
  453.     } else
  454.     {
  455.     v = malloc(sizeof(VARS));
  456.     vv = strdup(value);
  457.     vn = strdup(name);
  458.     if (v && vv && vn)
  459.     {
  460.         v->Str = vv;
  461.         v->Node.ln_Name = vn;
  462.         AddHead((LIST *)list, (NODE *)v);
  463.         return;
  464.     } /* if malloced */
  465.     } /* if (no) old node */
  466.  
  467.     /* --- if we didn't return prior, (if everything worked fine) remove all allocated data */
  468.     if (v)  free(v);
  469.     if (vv) free(vv);
  470.     if (vn) free(vn);
  471.     nomemory();
  472.     abort2();
  473. } /* SetVarIntoList */
  474.  
  475.  
  476.  
  477. /*
  478. **        Names 2 String
  479. **  copies all ln_Name s of a given List into a String and returns it
  480. **  (if filter != NULL the names are filtered before)
  481. **  There _must_ be a buffer big enough to fit all the Strings:
  482. **    definements in defs.h:
  483. **  BUFFERS is the number of "LINES" reserved for buffer
  484. **  and LINE_LENGTH (== 256) is the length of one such line
  485. **  <exec/lists.h> should be included
  486. **
  487. **  name2string does _not_ allocate memory!!!!
  488. **  currently filter MUST BE SET to NULL to guarantee compatibility to later versions!
  489. **  list MUST BE VALID! (there is no check)
  490. */
  491.  
  492. char*
  493. names2string (MLIST* list, char* buffer, char delimiter, char* (*filter)())
  494. {
  495.     struct Node* node;
  496.     char*     buf      = buffer;
  497.     int      i      = 0;
  498.     char     delim[2] =
  499.     {delimiter,0};
  500.     /* char    inter[128]; */
  501.  
  502.     node = (NODE*)list->mlh_Head;
  503.     while (node->ln_Succ && node != (NODE*)&list->mlh_Tail)
  504.     {
  505.     buffer = buf+i;
  506. /* ************************************ Hier gehoert noch der filter hin, ich brauchte ihn nur bisher noch nicht, daher liess ich ihn weg * */
  507.     if ((i += strlen(node->ln_Name)) < BUFFERS*LINE_LENGTH-1)
  508.     {
  509.         strcpy(buffer, node->ln_Name);
  510.         if (i < BUFFERS*LINE_LENGTH-1)
  511.         {
  512.         buffer = buf+i;
  513.         strcpy(buffer, delim);
  514.         i++;
  515.         } else
  516.         {
  517.         return(buf);
  518.         } /* if */
  519.     } else
  520.     {
  521.         break;
  522.     } /* if */
  523.     node = node->ln_Succ;
  524.     } /* while */
  525.  
  526.     *buffer = 0;
  527.     return(buf);
  528. } /* names2string */
  529.  
  530.  
  531.  
  532. /*
  533. ** numnodes() - return the number of entries in a list
  534. **
  535. **  list MUST BE VALID! (there is no check)
  536. */
  537.  
  538. int
  539. numnodes(MLIST* list)
  540. {
  541.     register int    i = 0;
  542.     register MNODE* n;
  543.  
  544.     for (n = list->mlh_Head; (n != NULL) && (n->mln_Succ != NULL); n = n->mln_Succ)
  545.     {
  546.     i++;
  547.     } /* for */
  548.     return(i);
  549. } /* numnodes */
  550.  
  551.  
  552.  
  553. /*
  554. ** findnode() - find a certain node in a list
  555. **
  556. **  search may be done up to a certain strlength (own function) or via FindName
  557. **
  558. **  list MUST BE VALID! (there is no check)
  559. */
  560.  
  561. NODE*
  562. findnode(MLIST* list, char* name, short len)
  563. {
  564.     register NODE* node;
  565.  
  566.     if (len)
  567.     {
  568.     for (node = (NODE*)list->mlh_Head; node && node->ln_Succ; node = node->ln_Succ)
  569.     {
  570.         if (strncmp(node->ln_Name, name, len) == 0)
  571.         {
  572.         return(node);
  573.         } /* if */
  574.     } /* for */
  575.     } else
  576.     {
  577.     return(FindName((LIST*)list, name));
  578.     } /* if */
  579.     return(NULL);
  580. } /* findnode */
  581.  
  582.  
  583. #endif /* (not) PATCH_AVL */
  584. /******************************************************************************
  585. *****  ENDE varsbases.c
  586. ******************************************************************************/
  587.  
  588.